﻿using System;
using System.Collections.Generic;
using System.Web;
using System.IO;


namespace CCPSIP.Sticker
{
    /// <summary>CCPSIP_025：下載個人貼圖檔案 API  /// </summary>
    /// idHeader = 裝置 UUID 前八碼。iOS 請使用 [CCPCrypto getIdHeader] 呼叫。
    /// checkcode = 裝置限時驗證碼。iOS 請使用 [CCPCrypto getCheckcode] 呼叫。
    /// DirName = 資料夾名稱。
    /// FileName = 檔案名稱。

    public class sticker_get : IHttpHandler
    {
        private const string kStickerDirDefault = @"\\192.168.19.1\Sticker_Default\Default";
        private const string kStickerRootDir = @"\\192.168.19.1\iSender_D";
        private const string kWinUserId = "ccpsip_cloud";
        private static byte[] kWinUserKey = { 0x59, 0x4C, 0x43, 0x71, 0x6A,
                                          0x6D, 0x44, 0x6A, 0x32, 0x5A,
                                          0x72, 0x62, 0x72, 0x43, 0x39,
                                          0x68, 0x51, 0x6E, 0x63, 0x6B,
                                          0x57, 0x32, 0x64, 0x74, 0x62
                                        };
        private const long kMaxFileLength = 5 * 1048576;// 5MB


        public void ProcessRequest(HttpContext context)
        {
            HttpRequest req = context.Request;
            HttpResponse resp = context.Response;
            resp.ContentType = "text/plain";
            resp.ContentEncoding = System.Text.Encoding.UTF8;
            DateTime reqTime = DateTime.Now;

            try
            {
                //【01】取得POST參數，驗證身分
                //
                string idHeader = req.Form["idHeader"];
                string checkcode = req.Form["checkcode"];
                string DirName = req.Form["DirName"];  //資料夾名稱
                string FileName = req.Form["FileName"];//檔案名稱

                SipUserInfo userInfo = SipKit.GetUserInfo(idHeader, checkcode, req);
                if (userInfo == null)
                {
                    throw new Exception("Error_01: Cannot identify this device");//無法識別此裝置
                }


                //【02】檢查檔案路徑問題(防路徑攻擊)
                //
                if (DirName.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0)
                {
                    throw new Exception("Error_02: Directory Name Error");//資料夾名稱錯誤
                }
                else if (FileName.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0)
                {
                    throw new Exception("Error_03: File Name Error");//檔案名稱錯誤
                }


                //【03】組合檔案路徑
                //
                string userDirName = userInfo.SIP_Num;
                if (SipKit.isHQMobileExt(userInfo.SIP_Num))
                {
                    userDirName = SipKit.getHQDesktopExt(userInfo.SIP_Num);
                }
                string stickerDir = string.Format(@"{0}\{1}\Stickers", kStickerRootDir, userDirName);
                string stickerPath = string.Format(@"{0}\{1}\{2}", stickerDir, DirName, FileName);


                //【04】切換網域身分存取資料夾
                //
                string tempCode = System.Text.Encoding.UTF8.GetString(kWinUserKey);

                using (new Tools.Impersonator(kWinUserId, "", tempCode))
                {
                    if (!File.Exists(stickerPath))
                    {
                        //找不到的話，試抓預設貼圖
                        stickerPath = string.Format(@"{0}\{1}\{2}", kStickerDirDefault, DirName, FileName);

                        if (!File.Exists(stickerPath))
                            throw new Exception("Error_04: File not found");//檔案不存在
                    }

                    FileInfo fInfo = new FileInfo(stickerPath);
                    if (fInfo.Length > kMaxFileLength)
                    {
                        throw new Exception("Error_05: File size exceeds limit");//檔案大小超過上限
                    }

                    //【99】回傳HTTP Header與圖片檔案
                    // http://en.wikipedia.org/wiki/List_of_HTTP_header_fields
                    //
                    resp.ContentType = "image/png";
                    resp.AppendHeader("Content-Length", fInfo.Length.ToString());
                    resp.AppendHeader("Last-Modified", fInfo.LastWriteTime.ToUniversalTime().ToString("r"));
                    resp.AppendHeader("Content-Disposition", ChrisKit.getContentDisposition(FileName));
                    resp.AppendHeader("Cache-Control", "no-cache");

                    if (fInfo.Length >= 4 * 1048576)
                        resp.TransmitFile(stickerPath);//Large File
                    else
                        resp.WriteFile(stickerPath, true);//Small File
                }//End of Impersonator
            }
            catch (Exception ex)
            {
                resp.ContentType = "application/xml";
                string resultStr = ChrisKit.Ex2Xml(ex, false);
                int contentLength = resp.ContentEncoding.GetByteCount(resultStr);
                resp.AppendHeader("Content-Length", contentLength.ToString());
                resp.Write(resultStr);
            }
            finally
            {
                resp.Flush();
                resp.Close();
            }
        }


        public bool IsReusable
        {
            get
            {
                return false;
            }
        }

    }
}
